/**
 * Copyright (c) 2009 Moogene
 * All rights reserved
 *
 * This software is the confidential and proprietary information of Moogene.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered into
 * with Moogene
 */

package com.moogene.android.engine.mmi;

import com.moogene.android.InfoMediator;
import com.moogene.android.engine.animlite.Animlite;
import com.moogene.android.engine.mmi.layout.Layout;
import com.moogene.android.engine.util.Anchor;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;

import java.util.ArrayList;

/**
 * @author Song, jiawei
 */
public abstract class Layer implements Cloneable {

	final private static int TOUCH_EXPEND = -10;

	public static final int ANCHOR_LEFT_TOP = 0;

	public static final int ANCHOR_CENTER = 1;

	public static final int ANCHOR_RIGHT_BOTTOM = 2;

	public static final int ANCHOR_CENTER_BOTTOM = 3;

	public static final int HUD = 100;

	public static final int TOP = 50;

	public static final int MIDDLE = 30;

	public static final int BOTTOM = 10;

	int mPrivateFlag = 0;

	protected int x;

	protected int y;

	protected int width;

	protected int height;

	private int priority;

	boolean isFocused;

	boolean isStartFocus;

	boolean isEndFocus;

	boolean isHold;

	private boolean isStartHold;

	boolean isEndHold;

	boolean isRealeased;

	boolean isStartDrag;

	boolean isEndDrag;

	boolean isDragged;

	boolean isHide;

	private ArrayList<Layer> innerLayers;

	private Layer outerLayer;

	private Layout layout;

	protected Layer copiedLayer;

	private Anchor anchor;

	// final private ArrayList<ActionListener> mActions;

	public Layer() {
		this(0, 0, MIDDLE);
	}

	public Layer(int width, int height) {
		this(width, height, MIDDLE);
	}

	public Layer(int width, int height, int priority) {
		this(0, 0, width, height, priority);
	}

	public Layer(int x, int y, int width, int height) {
		this(x, y, width, height, MIDDLE);
	}

	public Layer(int x, int y, int width, int height, int priority) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.priority = priority;
		setAnchor(Anchor.LEFT_TOP);
	}

	public void setAnchor(int Type) {
		anchor = new Anchor(Type, width, height);
	}

	public void setAnchor(int anchorX, int anchorY) {
		anchor = new Anchor(anchorX, anchorY, width, height);
	}

	/**
	 * @return the width
	 */
	public int getWidth() {
		return width;
	}

	/**
	 * @return the height
	 */
	public int getHeight() {
		return height;
	}

	public void setSize(int width, int height) {
		this.width = width;
		this.height = height;
	}

	/**
	 * @return the x
	 */
	public int getX() {
		return x;
	}

	/**
	 * @return the y
	 */
	public int getY() {
		return y;
	}

	public void setX(int x) {
		this.x = x;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void move(int dx, int dy) {
		x += dx;
		y += dy;
	}

	public int getAbsoluteX() {
		if (outerLayer == null) {
			return x;
		}
		return x + outerLayer.getAbsoluteX();
	}

	public int getAbsoluteY() {
		if (outerLayer == null) {
			return y;
		}
		return y + outerLayer.getAbsoluteY();
	}

	public void setLocation(int x, int y) {
		this.x = x;
		this.y = y;
	}

	public int getPriority() {
		return priority;
	}

	public void setPriority(int priority) {
		this.priority = priority;
	}

	public void initActionListeners() {

	}

	public void cache() {

	}

	public void unCache() {

	}

	public void setLayout(Layout layout) {
		this.layout = layout;
		layout.setSize(width, height);
	}

	public void addLayer(Layer layer) {
		if (innerLayers == null) {
			innerLayers = new ArrayList<Layer>();
		}
		layer.setPriority(priority);
		innerLayers.add(layer);
		if (layout != null) {
			layout.add(layer);
		}
		layer.outerLayer = this;
	}

	public void clear() {
		if (innerLayers != null) {
			innerLayers.clear();
		}
		if (layout != null) {
			layout.clear();
		}
	}

	public Layer getOuterLayer() {
		return outerLayer;
	}

	void clearOuterLayer() {
		outerLayer = null;
	}

	public ArrayList<Layer> getInnerLayers() {
		return innerLayers;
	}

	protected boolean canFoucs() {
		return false;
	}

	protected boolean canDragFree() {
		return false;
	}

	protected boolean canDragHorizontal() {
		return false;
	}

	protected boolean canDragVertical() {
		return false;
	}

	protected boolean canCopy() {
		return false;
	}

	protected boolean canAutoRemove() {
		return false;
	}

	protected Animlite getAttachedAnimlite() {
		return null;
	}

	protected boolean willfollowCameraWhenDrag() {
		return true;
	}

	protected Layer copy() {
		copiedLayer = clone();
		return copiedLayer;
	}

	public Layer getLastCopied() {
		return copiedLayer;
	}

	public boolean isStartFocus() {
		return isStartFocus;
	}

	void setStartFocus(boolean isStartFocus) {
		this.isStartFocus = isStartFocus;
	}

	public boolean isEndFocus() {
		return isEndFocus;
	}

	void setEndFocus(boolean isEndFocus) {
		this.isEndFocus = isEndFocus;
	}

	/**
	 * @return the isFocused
	 */
	public boolean isFocused() {
		return isFocused;
	}

	/**
	 * @param isFocused
	 *            the isFocused to set
	 */
	void setFocused(boolean isFocused) {
		this.isFocused = isFocused;
		if (isFocused) {
			isStartFocus = true;
		} else {
			isEndFocus = true;
		}
	}

	/**
	 * @return the isHold
	 */
	public boolean isHold() {
		return isHold;
	}

	/**
	 * @param isHold
	 *            the isHold to set
	 */
	void setHold(boolean isHold) {
		this.isHold = isHold;
		if (isHold) {
			isStartHold = true;
		} else {
			isEndHold = true;
		}
	}

	public boolean isStartHold() {
		return isStartHold;
	}

	/**
	 * @return the isEndHold
	 */
	public boolean isEndHold() {
		return isEndHold;
	}

	public void setRealeased(boolean release) {
		isRealeased = release;
	}

	public boolean isRealeased() {
		return isRealeased;
	}

	/**
	 * @return the isDragged
	 */
	public boolean isDragged() {
		return isDragged;
	}

	/**
	 * @param isDragged
	 *            the isDragged to set
	 */
	void setDragged(boolean isDragged) {
		this.isDragged = isDragged;
	}

	void checkBoarderWhenDrag() {
		if (canDragHorizontal()) {
			if (x > 0) {
				x = 0;
			}
			if (x + width < InfoMediator.getScreenWidth()) {
				x = InfoMediator.getScreenWidth() - width;
			}
		}
		if (canDragVertical()) {
			if (y > 0) {
				y = 0;
			}
			if (y + height < InfoMediator.getScreenHeight()) {
				y = InfoMediator.getScreenHeight() - height;
			}
		}
	}

	public void draw(Canvas canvas) {
		if (innerLayers != null) {
			int count = canvas.save();
			canvas.translate(x, y);
			for (Layer l : innerLayers) {
				l.draw(canvas);
			}
			canvas.restoreToCount(count);
		}
		Animlite anim = getAttachedAnimlite();
		if (anim != null) {
			anim.draw(canvas, x, y);
			if (Config.UI_DEBUG) {
				Paint p = new Paint();
				p.setStyle(Style.FILL_AND_STROKE);
				p.setColor(0x95FFFF00);
				canvas.drawRect(getDstRect(), p);
				p.setColor(0x9500FFFF);
				canvas.drawRect(getTouchRect(), p);
				p.setColor(Color.RED);
				canvas.drawCircle(x, y, 5, p);
			}
		}
	}

	public void hide() {
		isHide = true;
	}

	public void unHide() {
		isHide = false;
	}

	public boolean isHide() {
		return isHide;
	}

	public void update() {
		if (innerLayers != null) {
			for (Layer l : innerLayers) {
				l.update();
			}
		}
	}

	void updateState() {
		if (innerLayers != null) {
			for (Layer l : innerLayers) {
				l.updateState();
			}
		}
		if (isStartHold) {
			isStartHold = false;
		}
		if (isEndHold) {
			isEndHold = false;
		}
		if (isStartFocus) {
			isStartFocus = false;
		}
		if (isEndFocus) {
			isEndFocus = false;
		}
		if (isRealeased) {
			isRealeased = false;
		}
	}

	public Rect getDstRect() {
		Rect r;
		Animlite anim = getAttachedAnimlite();
		if (anim != null) {
			r = anim.getDstRect(x, y);
		} else {
			r = anchor.adjust(x, y);
		}
		return r;
	}

	public Rect getTouchRect() {
		Rect r = getDstRect();
		if (outerLayer != null) {
			r.offset(outerLayer.getAbsoluteX(), outerLayer.getAbsoluteY());
		}
		r.inset(TOUCH_EXPEND, TOUCH_EXPEND);
		return r;
	}

	public void fillColor(Canvas c, int color) {
		// TODO: optimize new
		Paint p = new Paint();
		p.setColor(color);
		c.drawRect(getDstRect(), p);
	}

	@Override
	public Layer clone() {
		Layer l = null;
		try {
			l = (Layer) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return l;
	}

}
